/**
 * Vue组件封装smooth-dnd的容器功能，提供拖放排序的核心功能
 *
 * 该组件封装了smooth-dnd库的主要功能，处理容器生命周期、事件绑定和DOM渲染。
 * 支持垂直/水平方向、动画配置、拖放策略等多种拖放场景配置。
 *
 * @emits {Function} drag-start - 拖动开始时触发
 * @emits {Function} drag-end - 拖动结束时触发
 * @emits {Function} drop - 完成拖放时触发
 * @emits {Function} drag-enter - 拖拽元素进入容器时触发
 * @emits {Function} drag-leave - 拖拽元素离开容器时触发
 * @emits {Function} drop-ready - 拖放准备就绪时触发
 *
 * @prop {String} orientation - 容器方向，默认'vertical'
 * @prop {Boolean} removeOnDropOut - 是否在拖出时移除元素，默认false
 * @prop {Boolean} autoScrollEnabled - 是否启用自动滚动，默认true
 * @prop {Number} animationDuration - 动画时长(ms)，默认250
 * @prop {String} behaviour - 容器行为模式
 * @prop {String} groupName - 拖放组标识，允许跨容器拖放
 * @prop {String} dragHandleSelector - 拖拽手柄选择器
 * @prop {String} nonDragAreaSelector - 非拖拽区域选择器
 * @prop {String} lockAxis - 锁定拖动轴向
 * @prop {String} dragClass - 拖拽时应用的CSS类
 * @prop {String} dropClass - 放置时应用的CSS类
 * @prop {Number} dragBeginDelay - 拖拽开始延迟时间(ms)
 * @prop {Function} getChildPayload - 获取子元素数据负载的方法
 * @prop {Function} shouldAnimateDrop - 控制是否播放放置动画的方法
 * @prop {Function} shouldAcceptDrop - 控制是否接受放置的方法
 * @prop {Function} getGhostParent - 获取幽灵元素父节点的方法
 * @prop {Object|Boolean} dropPlaceholder - 放置占位符配置
 * @prop {String|Object} tag - 容器根元素标签，默认'div'
 */
import type { SmoothDnD } from 'smooth-dnd'
import { dropHandlers, smoothDnD } from 'smooth-dnd'
import { defineComponent, h } from 'vue'

import { getTagProps, validateTagProp } from './utils'

// 初始化smooth-dnd全局配置
smoothDnD.dropHandler = dropHandlers.reactDropHandler().handler
// 禁用自动包裹子元素
smoothDnD.wrapChild = false

type EventKey = 'drag-start' | 'drag-end' | 'drop' | 'drag-enter' | 'drag-leave' | 'drop-ready'

const eventEmitterMap: Record<EventKey, string> = {
  'drag-start': 'onDragStart',
  'drag-end': 'onDragEnd',
  drop: 'onDrop',
  'drag-enter': 'onDragEnter',
  'drag-leave': 'onDragLeave',
  'drop-ready': 'onDropReady'
}

export const SmoothDndContainer = defineComponent({
  name: 'SmoothDndContainer',
  setup() {
    // 保存smooth-dnd容器实例的引用
    return {
      container: null as SmoothDnD | null
    }
  },
  mounted() {
    // 初始化容器配置，绑定事件监听器
    const options: any = Object.assign({}, this.$props)
    // 将事件监听器映射到smooth-dnd的配置选项
    for (const key in eventEmitterMap) {
      const eventKey = key as EventKey
      options[eventEmitterMap[eventKey]] = (props: any) => {
        this.$emit(eventKey, props)
      }
    }
    // 获取容器DOM元素并初始化smooth-dnd实例
    const containerElement = this.$refs.container || this.$el
    this.container = smoothDnD(containerElement, options)
  },
  unmounted() {
    if (this.container) {
      try {
        this.container.dispose()
      } catch {
        // ignore
      }
    }
  },
  emits: ['drop', 'drag-start', 'drag-end', 'drag-enter', 'drag-leave', 'drop-ready'],
  props: {
    orientation: { type: String, default: 'vertical' },
    removeOnDropOut: { type: Boolean, default: false },
    autoScrollEnabled: { type: Boolean, default: true },
    animationDuration: { type: Number, default: 250 },
    behaviour: String,
    groupName: String,
    dragHandleSelector: String,
    nonDragAreaSelector: String,
    lockAxis: String,
    dragClass: String,
    dropClass: String,
    dragBeginDelay: Number,
    getChildPayload: Function,
    shouldAnimateDrop: Function,
    shouldAcceptDrop: Function,
    getGhostParent: Function,
    dropPlaceholder: [Object, Boolean],
    tag: {
      validator: validateTagProp,
      default: 'div'
    }
  },
  render() {
    // 动态生成容器标签和属性
    const tagProps = getTagProps(this)
    console.log('SmoothDndContainer tagProps', tagProps)
    return h(
      tagProps.value,
      Object.assign({}, { ref: 'container' }, tagProps.props),
      this.$slots.default?.()
    )
  }
})
